<script setup lang="ts">
  import { ref, computed, defineAsyncComponent, useAttrs, watch } from "vue";
  import { ElDialog } from "element-plus";

  export type Open = typeof open;
  type TypeElDialog = CPN<typeof ElDialog>;
  interface Props extends /* @vue-ignore */ TypeElDialog {
    appendToBody?: boolean;
    zIndex?: number;
    placeholder?: string;
    hideLabel?: boolean;
    type?: Type;
    modelValue?: string;
    disabled?: boolean;
  }
  interface Values {
    goods: gt.sql.goods;
    prize: gt.sql.prize;
    user: gt.sql.user;
  }
  type Type = Key<Values>;
  let resolve: cbk, reject: cbk;
  const
    props = withDefaults(defineProps<Props>(), { appendToBody: true, zIndex: 3 }),
    ua = useAttrs(),
    attrs = computed(() => {
      return { ...props, ...ua };
    }),
    txt = computed(() => {
      return data.value?.name || "";
    }),
    stxt = ref(""),
    srtxt = computed(() => {
      return stxt.value ? stxt.value : (props.placeholder || "未选择");
    }),
    data = ref(),
    show = ref(false),
    dialogTitle = ref(""),
    cmpType = ref<Type>("goods"),
    cmp = computed(() => {
      switch (cmpType.value) {
        case "goods": return defineAsyncComponent(() => import("@/views/baseInfo/goods.vue"));
        case "prize": return defineAsyncComponent(() => import("@/views/draw/prize.vue"));
        case "user": return defineAsyncComponent(() => import("@/views/baseInfo/user.vue"));

        default:
          break;
      }
    }),
    emit = defineEmits<{
      (e: "click", cbk: typeof open): void;
      (e: "update:modelValue", v: string | undefined): void;
    }>()
    ;
  function confirm() {
    stxt.value = data.value?.name || "";
    if (resolve instanceof Function) {
      resolve(data.value);
    }
    emit("update:modelValue", data.value?.id);
    show.value = false;
  }
  function cancel() {
    if (reject instanceof Function) {
      reject();
    }
  }
  function open<T extends Type>(type: T, title?: string) {
    return new Promise<Values[T] | undefined>((res, rej) => {
      cmpType.value = type;
      dialogTitle.value = props.title || title || "请选择";
      resolve = res; reject = rej;
      show.value = true;
    });
  }
  watch(show, n => {
    if (!n) {
      data.value = undefined;
      cancel();
    }
  });
  defineExpose({ open });
  function labelClick() {
    if (!props.disabled && !props.hideLabel && props.type) {
      cmpType.value = props.type;
      dialogTitle.value = props.title || "请选择";
      resolve = reject = () => { };
      show.value = true;
    }
    emit('click', open);
  }
  watch(() => props.modelValue, async (n) => {
    data.value = await gd[props.type || cmpType.value].getById(n as string);
    stxt.value = data.value?.name || "";
  }, { immediate: true });
</script>
<template>
  <div class="whf oh x fg1 SelectBase" :class="disabled ? 'disabled' : 'sbss'" @click.stop="labelClick">
    <span class="txt-hid" v-if="!hideLabel" @click.stop="labelClick">{{ srtxt }}</span>
    <ElDialog class="Dialog" v-if="show" :="attrs" :title="dialogTitle" v-model="show" @click.stop="">
      <div><span class="mr1em">当前选择:</span><span>{{ txt }}</span></div>
      <component :is="cmp" v-model="data" />
      <template v-if="!$slots.footer" #footer>
        <el-button type="success" @click="show = false">取消</el-button>
        <el-button type="primary" @click="confirm">确定</el-button>
      </template>
    </ElDialog>
  </div>
</template>
